using UnityEngine;

namespace VoxelGame.NPC
{
	public class Follow : NPCBehaviour
	{
		[SerializeField]
		private float _walkSpeed = 2f;

		[SerializeField]
		private float _runSpeed = 4f;

		[SerializeField]
		private float _angularSpeed = 2f;

		[SerializeField]
		private Vector3 _lineOfSight = new Vector3(0f, 0.5f, 0f);

		[SerializeField]
		private float _avoidObstacleDistance = 5f;

		[SerializeField]
		private string _tagTarget;

		[SerializeField]
		private string _idleAnimation;

		[SerializeField]
		private string _walkAnimation;

		[SerializeField]
		private string _runAnimation;

		private Transform _target;

		private Quaternion _targetRotation;

		private bool _turnArround;

		private float _speed;

		private void Start()
		{
			GameObject gameObject = GameObject.FindWithTag(_tagTarget);
			if (gameObject != null)
			{
				_target = gameObject.transform;
			}
			else
			{
				UnityEngine.Debug.LogError("[" + base.gameObject.name + "] There is no target with the following tag: " + _tagTarget);
			}
		}

		private void OnEnable()
		{
			PlayAnimation(_walkAnimation);
		}

		private void Update()
		{
			Move();
			AvoidObstacles();
			UpdateHeading();
		}

		private void UpdateHeading()
		{
			Vector3 forward = _target.position - base.transform.position;
			_targetRotation = Quaternion.LookRotation(forward, Vector3.up);
			Vector3 eulerAngles = _targetRotation.eulerAngles;
			_targetRotation = Quaternion.AngleAxis(eulerAngles.y, Vector3.up);
		}

		private void Move()
		{
			float num = Vector3.Distance(_target.position, base.transform.position);
			if (num > 5f)
			{
				if (num <= 10f)
				{
					_speed = _walkSpeed;
					PlayAnimation(_walkAnimation);
				}
				else
				{
					_speed = _runSpeed;
					PlayAnimation(_runAnimation);
				}
				base.transform.rotation = Quaternion.Slerp(base.transform.rotation, _targetRotation, Time.deltaTime * _angularSpeed);
				Vector3 a = base.transform.TransformDirection(Vector3.forward);
				_npcControls.SimpleMove(a * _speed);
			}
			else
			{
				_npcControls.SimpleMove(Vector3.zero);
				PlayAnimation(_idleAnimation);
			}
		}

		private void AvoidObstacles()
		{
			float angleDirection = 0f;
			if (ForwardRayCast(out angleDirection, _npcControls.ColliderRadius()) || ForwardRayCast(out angleDirection, 0f - _npcControls.ColliderRadius()) || ForwardRayCast(out angleDirection, 0f))
			{
				TurnArround(angleDirection);
			}
			else
			{
				_turnArround = false;
			}
		}

		private void TurnArround(float angleDirection)
		{
			_turnArround = true;
			_targetRotation = Quaternion.AngleAxis(angleDirection, Vector3.up);
		}

		private bool ForwardRayCast(out float angleDirection, float xOffset)
		{
			Vector3 vector = _lineOfSight;
			vector.x += xOffset;
			vector = base.transform.TransformPoint(vector);
			if (_turnArround)
			{
				UnityEngine.Debug.DrawRay(vector, base.transform.forward * _avoidObstacleDistance, Color.red);
			}
			else
			{
				UnityEngine.Debug.DrawRay(vector, base.transform.forward * _avoidObstacleDistance, Color.blue);
			}
			RaycastHit hitInfo;
			bool flag = Physics.Raycast(vector, base.transform.forward, out hitInfo, _avoidObstacleDistance);
			if (flag)
			{
				Vector3 vector2 = hitInfo.normal * (_avoidObstacleDistance - hitInfo.distance) * 20f;
				angleDirection = vector2.x + vector2.z;
			}
			else
			{
				angleDirection = 0f;
			}
			return flag;
		}
	}
}
